/*
 * IfInstruction.cpp
 *
 *  Created on: 28/dic/2010
 *      Author: computer
 */

#include "IfInstruction.h"
#include "Bool.h"
#include "Null.h"
#include <sstream>

namespace TreeExpression {

IfInstruction::IfInstruction() : FlowExpression(), Expression_CRTP<IfInstruction>(), stop(false), executed(false) { }

IfInstruction::IfInstruction(const IfInstruction& copy) : Expression(copy), FlowExpression(copy), Expression_CRTP<IfInstruction>(copy), stop(copy.stop), executed(copy.executed), condition(copy.condition), listInstruction(copy.listInstruction) { }

IfInstruction::~IfInstruction() { }

AutoPointer<Expression> IfInstruction::eval(CopyPointer<Context>& context) {
	CopyPointer<Context> localContext(new Context(context.get(), "local_if"));
	AutoPointer<Expression> risCondition = condition->eval(localContext);
	Bool* test = dynamic_cast<Bool*>(risCondition.get());
	if (test && test->getData()) {
		executed = true;
		std::list< AutoPointer<Expression> >::iterator i;
		for (i = listInstruction.begin(); i != listInstruction.end(); ++i) {
			FlowExpression* instruction = dynamic_cast<FlowExpression*>(i->get());
			if (!instruction) {
				(*i)->eval(localContext);
			}
			else {
				AutoPointer<Expression> ris = instruction->eval(localContext);
				if (instruction->isStop()) {//If it is a stop instruction (i.e.: return)
					stop = true;
					if (ris->hasSon()) return ris;//Return the instruction of return and not the result
					else return AutoPointer<TreeExpression::Expression>(new TreeExpression::Null());
				}
			}
		}
	}
	return AutoPointer<TreeExpression::Expression>(new TreeExpression::Null());
}

std::string IfInstruction::toString() const {
	std::ostringstream oss;
	oss << "if (" << condition->toString() << ") ";
	//TODO
	return oss.str();
}

bool IfInstruction::isStop() const {
	return stop;
}

bool IfInstruction::isExecuted() const {
	return executed;
}

void IfInstruction::setCondition(const AutoPointer<Expression>& _condition) {
	condition = _condition;
}

void IfInstruction::addInstruction(const AutoPointer<Expression>& toAdd) {
	listInstruction.push_back(toAdd);
}

Expression* IfInstruction::clone() const {
	IfInstruction* ris = new IfInstruction();
	ris->stop = stop;
	ris->executed = executed;
	std::list< AutoPointer<Expression> >::const_iterator i;
	for (i = listInstruction.begin(); i != listInstruction.end(); ++i) {
		ris->addInstruction(AutoPointer<Expression>((*i)->cloneTree()));
	}
	ris->setCondition(AutoPointer<Expression>(this->condition->cloneTree()));
	return ris;
}

}


